#include "mainwindow.hpp"

#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    _connexion = new Connexion(this);
    _lobby = new Lobby(this);
    _reseau = new Reseau(_lobby, this, this);
    _lobby->setReseau(_reseau);

    setCentralWidget(_connexion);

    _lobby->hide();
    _lobby->hideDocks();
    resize(175,50);
    move(10, 350);

    connect(_connexion, SIGNAL(connexion(int)), _reseau, SLOT(connect(int)));
    connect(_reseau, SIGNAL(impossibleToBoundPort(int)), this, SLOT(reactConnectionFailed(int)));
    connect(_reseau, SIGNAL(serverBound()), this, SLOT(reactConnectionSuccess()));
    connect(_lobby, SIGNAL(kick(QString)), _reseau, SLOT(kick(QString)));

    setWindowIcon(QIcon("img/icon.png"));
    setWindowTitle("Go Server");
}

MainWindow::~MainWindow()
{

}

void MainWindow::reactConnectionSuccess()
{
    displayLobby();
}

void MainWindow::reactConnectionFailed(int port)
{
    QMessageBox::critical(this, "Error", QString("Port " + QString::number(port) + " is already bound"));
}

void MainWindow::displayLobby()
{
    _connexion->hide();
    _lobby->showDocks();
    resize(400, 300);
}

void MainWindow::reactCreateGame(quint8 goban, qreal komi)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if ((goban == 9 or
        goban == 13 or
        goban == 19) and
        komi >= 0 and
        komi <= 10)
    {
        Game * game = new Game(_lobby, client, goban, komi, this);

        _gameHash[game->id()] = game;

        qWarning() << "Creating game " << game->id();

        _reseau->sendAll(Mid::GAMECREATED, game->id(), goban, komi, client->name());
    }
    else
    {
        client->send(Mid::GAMECREATIONFAILED);
    }
}

void MainWindow::reactGameDestroy(quint8 id)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if (_gameHash.contains(id))
    {
        if (_gameHash[id]->destroy(client))
        {
            _lobby->removeGame(id);

            _gameHash[id]->deleteLater();
            _gameHash.remove(id);

            _reseau->sendAll(Mid::GAMEDESTROYED, id);
        }
        else
            client->send(Mid::ILLEGALMESSAGE, "You cannot delete this game (you may not be the owner, or the game may have already started)");
    }
}

void MainWindow::reactGameQuit(quint8 id)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if (_gameHash.contains(id))
        _gameHash[id]->clientLeft(client->name());
}

void MainWindow::reactWantToSee(quint8 id)
{
    Client * observer = qobject_cast<Client *>(sender());

    if (observer == 0)
        return;

    if (_gameHash.contains(id))
        _gameHash[id]->addObserver(observer);
    else
    {
        observer->send(Mid::NOTEXISTS, id);
    }
}

void MainWindow::reactWantToPlay(quint8 id)
{
    Client * player = qobject_cast<Client *>(sender());

    if (player == 0)
        return;

    if (_gameHash.contains(id))
        _gameHash[id]->addPlayer(player);
    else
    {
        player->send(Mid::NOTEXISTS, id);
    }
}

void MainWindow::reactDontWantToSeeAnymore(quint8 id)
{
    Client * observer = qobject_cast<Client *>(sender());

    if (observer == 0)
        return;

    if (_gameHash.contains(id))
        _gameHash[id]->clientLeft(observer->name());
}

void MainWindow::reactGameSay(quint8 id, const QString & message)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if (_gameHash.contains(id))
    {
        _gameHash[id]->someoneSaid(client->name(), message);
    }
}

void MainWindow::destroyGame(quint8 id)
{
    if (_gameHash.contains(id))
    {
        _lobby->removeGame(id);

        _gameHash[id]->deleteLater();
        _gameHash.remove(id);

        _reseau->sendAll(Mid::GAMEDESTROYED, id);
    }
}

QList<Game *> MainWindow::gameList() const
{
    QList<Game *> list;

    for (QHashIterator<quint8, Game *> it(_gameHash); it.hasNext();)
    {
        it.next();
        list.append(it.value());
    }
    return list;
}

void MainWindow::reactPlayMove(quint8 id, quint8 x, quint8 y)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if (_gameHash.contains(id))
        _gameHash[id]->reactPlayMove(client, x, y);
}

void MainWindow::reactToPlay(quint8 id)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if (_gameHash.contains(id))
        _gameHash[id]->reactToPlay(client);
}

void MainWindow::reactValidateGroups(quint8 id)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if (_gameHash.contains(id))
        _gameHash[id]->reactValidateGroups(client);
}

void MainWindow::reactSkipTurn(quint8 id)
{
    Client * client = qobject_cast<Client *>(sender());

    if (client == 0)
        return;

    if (_gameHash.contains(id))
        _gameHash[id]->skipTurn(client);
}

void MainWindow::reactDeadGroup(quint8 id, quint8 x, quint8 y)
{
    if (_gameHash.contains(id))
        _gameHash[id]->reactDeadGroup(x, y);
}

void MainWindow::reactAliveGroup(quint8 id, quint8 x, quint8 y)
{
    if (_gameHash.contains(id))
        _gameHash[id]->reactAliveGroup(x, y);
}
